home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / PROGRAMR / OLE2BOOK.ZIP / CHAP06.ZIP / CHAP06 / EDATAOBJ / DDATAOBJ.CPP < prev    next >
C/C++ Source or Header  |  1993-03-28  |  8KB  |  350 lines

  1. /*
  2.  * DDATAOBJ.CPP
  3.  *
  4.  * Data object implemented in a DLL supporting the IDataObject interface.
  5.  *
  6.  * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
  7.  *
  8.  * Kraig Brockschmidt, Software Design Engineer
  9.  * Microsoft Systems Developer Relations
  10.  *
  11.  * Internet  :  kraigb@microsoft.com
  12.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  13.  */
  14.  
  15.  
  16. #define INITGUIDS
  17. #include "ddataobj.h"
  18.  
  19.  
  20. //Count number of objects and number of locks.
  21. ULONG       g_cObj=0;
  22. ULONG       g_cLock=0;
  23.  
  24. //Make this global for the data object to load resources.
  25. HINSTANCE   g_hInst=NULL;
  26.  
  27.  
  28. /*
  29.  * LibMain
  30.  *
  31.  * Purpose:
  32.  *  DLL-specific entry point called from LibEntry.
  33.  *
  34.  * Parameters:
  35.  *  hInst           HINSTANCE instance of the DLL.
  36.  *  wDataSeg        WORD segment selector of the DLL's data segment.
  37.  *  wHeapSize       WORD byte count of the heap.
  38.  *  lpCmdLine       LPSTR to command line used to start the module.
  39.  *
  40.  * Return Value:
  41.  *  HANDLE          Instance handle of the DLL.
  42.  *
  43.  */
  44.  
  45. HANDLE FAR PASCAL LibMain(HINSTANCE hInst, WORD wDataSeg
  46.     , WORD cbHeapSize, LPSTR lpCmdLine)
  47.     {
  48.     if (0!=cbHeapSize)
  49.         UnlockData(0);
  50.  
  51.     g_hInst=hInst;
  52.     return hInst;
  53.     }
  54.  
  55.  
  56.  
  57.  
  58.  
  59. /*
  60.  * WEP
  61.  *
  62.  * Purpose:
  63.  *  Required DLL Exit function.  Does nothing.
  64.  *
  65.  * Parameters:
  66.  *  bSystemExit     BOOL indicating if the system is being shut
  67.  *                  down or the DLL has just been unloaded.
  68.  *
  69.  * Return Value:
  70.  *  void
  71.  *
  72.  */
  73.  
  74. void FAR PASCAL WEP(int bSystemExit)
  75.     {
  76.     return;
  77.     }
  78.  
  79.  
  80.  
  81.  
  82.  
  83.  
  84. /*
  85.  * DllGetClassObject
  86.  *
  87.  * Purpose:
  88.  *  Provides an IClassFactory for a given CLSID that this DLL is
  89.  *  registered to support.  This DLL is placed under the CLSID
  90.  *  in the registration database as the InProcServer.
  91.  *
  92.  * Parameters:
  93.  *  clsID           REFCLSID that identifies the class factory desired.
  94.  *                  Since this parameter is passed this DLL can handle
  95.  *                  any number of objects simply by returning different
  96.  *                  class factories here for different CLSIDs.
  97.  *
  98.  *  riid            REFIID specifying the interface the caller wants
  99.  *                  on the class object, usually IID_ClassFactory.
  100.  *
  101.  *  ppv             LPVOID FAR * in which to return the interface pointer.
  102.  *
  103.  * Return Value:
  104.  *  HRESULT         NOERROR on success, otherwise contains an error SCODE.
  105.  */
  106.  
  107. HRESULT __export FAR PASCAL DllGetClassObject(REFCLSID rclsid, REFIID riid
  108.     , LPVOID FAR *ppv)
  109.     {
  110.     //Check that we can provide the interface
  111.     if (!IsEqualIID(riid, IID_IUnknown) && !IsEqualIID(riid, IID_IClassFactory))
  112.         return ResultFromScode(E_NOINTERFACE);
  113.  
  114.     *ppv=NULL;
  115.  
  116.     //Check each of the three CLSIDs we support.
  117.     if (IsEqualCLSID(rclsid, CLSID_DataObjectSmall))
  118.         *ppv=(LPVOID)new CDataObjectClassFactory(DOSIZE_SMALL);
  119.  
  120.     if (IsEqualCLSID(rclsid, CLSID_DataObjectMedium))
  121.         *ppv=(LPVOID)new CDataObjectClassFactory(DOSIZE_MEDIUM);
  122.  
  123.     if (IsEqualCLSID(rclsid, CLSID_DataObjectLarge))
  124.         *ppv=(LPVOID)new CDataObjectClassFactory(DOSIZE_LARGE);
  125.  
  126.     if (NULL==*ppv)
  127.         return ResultFromScode(E_OUTOFMEMORY);
  128.  
  129.     //Don't forget to AddRef the object through any interface we return
  130.     ((LPUNKNOWN)*ppv)->AddRef();
  131.  
  132.     return NOERROR;
  133.     }
  134.  
  135.  
  136.  
  137.  
  138.  
  139. /*
  140.  * DllCanUnloadNow
  141.  *
  142.  * Purpose:
  143.  *  Answers if the DLL can be freed, that is, if there are no
  144.  *  references to anything this DLL provides.
  145.  *
  146.  * Parameters:
  147.  *  None
  148.  *
  149.  * Return Value:
  150.  *  BOOL            TRUE if nothing is using us, FALSE otherwise.
  151.  */
  152.  
  153. STDAPI DllCanUnloadNow(void)
  154.     {
  155.     SCODE   sc;
  156.  
  157.     //Our answer is whether there are any object or locks
  158.     sc=(0L==g_cObj && 0==g_cLock) ? S_OK : S_FALSE;
  159.     return ResultFromScode(sc);
  160.     }
  161.  
  162.  
  163.  
  164.  
  165. /*
  166.  * ObjectDestroyed
  167.  *
  168.  * Purpose:
  169.  *  Function for the DataObject object to call when it gets destroyed.
  170.  *  Since we're in a DLL we only track the number of objects here
  171.  *  letting DllCanUnloadNow take care of the rest.
  172.  *
  173.  * Parameters:
  174.  *  None
  175.  *
  176.  * Return Value:
  177.  *  None
  178.  */
  179.  
  180. void FAR PASCAL ObjectDestroyed(void)
  181.     {
  182.     g_cObj--;
  183.     return;
  184.     }
  185.  
  186.  
  187.  
  188.  
  189.  
  190. /*
  191.  * CDataObjectClassFactory::CDataObjectClassFactory
  192.  * CDataObjectClassFactory::~CDataObjectClassFactory
  193.  *
  194.  * Constructor Parameters:
  195.  *  iSize           UINT specifying the data size for this class.
  196.  */
  197.  
  198. CDataObjectClassFactory::CDataObjectClassFactory(UINT iSize)
  199.     {
  200.     m_cRef=0L;
  201.     m_iSize=iSize;
  202.     return;
  203.     }
  204.  
  205.  
  206. CDataObjectClassFactory::~CDataObjectClassFactory(void)
  207.     {
  208.     return;
  209.     }
  210.  
  211.  
  212.  
  213.  
  214.  
  215.  
  216. /*
  217.  * CDataObjectClassFactory::QueryInterface
  218.  * CDataObjectClassFactory::AddRef
  219.  * CDataObjectClassFactory::Release
  220.  */
  221.  
  222. STDMETHODIMP CDataObjectClassFactory::QueryInterface(REFIID riid, LPVOID FAR *ppv)
  223.     {
  224.     *ppv=NULL;
  225.  
  226.     //Any interface on this object is the object pointer.
  227.     if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory))
  228.         *ppv=(LPVOID)this;
  229.  
  230.     /*
  231.      * If we actually assign an interface to ppv we need to AddRef it
  232.      * since we're returning a new pointer.
  233.      */
  234.     if (NULL!=*ppv)
  235.         {
  236.         ((LPUNKNOWN)*ppv)->AddRef();
  237.         return NOERROR;
  238.         }
  239.  
  240.     return ResultFromScode(E_NOINTERFACE);
  241.     }
  242.  
  243.  
  244. STDMETHODIMP_(ULONG) CDataObjectClassFactory::AddRef(void)
  245.     {
  246.     return ++m_cRef;
  247.     }
  248.  
  249.  
  250. STDMETHODIMP_(ULONG) CDataObjectClassFactory::Release(void)
  251.     {
  252.     ULONG           cRefT;
  253.  
  254.     cRefT=--m_cRef;
  255.  
  256.     if (0L==m_cRef)
  257.         delete this;
  258.  
  259.     return cRefT;
  260.     }
  261.  
  262.  
  263.  
  264.  
  265.  
  266.  
  267.  
  268. /*
  269.  * CDataObjectClassFactory::CreateInstance
  270.  *
  271.  * Purpose:
  272.  *  Instantiates a DataObject object that supports the IDataObject
  273.  *  and IUnknown interfaces.  If the caller asks for a different
  274.  *  interface than these two then we fail.
  275.  *
  276.  * Parameters:
  277.  *  punkOuter       LPUNKNOWN to the controlling IUnknown if we are
  278.  *                  being used in an aggregation.
  279.  *  riid            REFIID identifying the interface the caller desires
  280.  *                  to have for the new object.
  281.  *  ppvObj          LPVOID FAR * in which to store the desired interface
  282.  *                  pointer for the new object.
  283.  *
  284.  * Return Value:
  285.  *  HRESULT         NOERROR if successful, otherwise contains E_NOINTERFACE
  286.  *                  if we cannot support the requested interface.
  287.  */
  288.  
  289. STDMETHODIMP CDataObjectClassFactory::CreateInstance(LPUNKNOWN punkOuter
  290.     , REFIID riid, LPVOID FAR *ppvObj)
  291.     {
  292.     LPCDataObject       pObj;
  293.     HRESULT             hr;
  294.  
  295.     *ppvObj=NULL;
  296.     hr=ResultFromScode(E_OUTOFMEMORY);
  297.  
  298.     //Verify that if there is a controlling unknown it's asking for IUnknown
  299.     if (NULL!=punkOuter && !IsEqualIID(riid, IID_IUnknown))
  300.         return ResultFromScode(E_NOINTERFACE);
  301.  
  302.     //Create the object telling it the data size to work with
  303.     pObj=new CDataObject(punkOuter, ObjectDestroyed, m_iSize);
  304.  
  305.     if (NULL==pObj)
  306.         return hr;
  307.  
  308.     if (pObj->FInit())
  309.         hr=pObj->QueryInterface(riid, ppvObj);
  310.  
  311.     //Kill the object if initial creation or FInit failed.
  312.     if (FAILED(hr))
  313.         delete pObj;
  314.     else
  315.         g_cObj++;
  316.  
  317.     return hr;
  318.     }
  319.  
  320.  
  321.  
  322.  
  323.  
  324.  
  325. /*
  326.  * CDataObjectClassFactory::LockServer
  327.  *
  328.  * Purpose:
  329.  *  Increments or decrements the lock count of the DLL.  If the lock
  330.  *  count goes to zero and there are no objects, the DLL is allowed
  331.  *  to unload.  See DllCanUnloadNow.
  332.  *
  333.  * Parameters:
  334.  *  fLock           BOOL specifying whether to increment or decrement the
  335.  *                  lock count.
  336.  *
  337.  * Return Value:
  338.  *  HRESULT         NOERROR always.
  339.  */
  340.  
  341. STDMETHODIMP CDataObjectClassFactory::LockServer(BOOL fLock)
  342.     {
  343.     if (fLock)
  344.         g_cLock++;
  345.     else
  346.         g_cLock--;
  347.  
  348.     return NOERROR;
  349.     }
  350.